package org.xiaojl.xcloud.tools.gateway.accesslog;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xiaojl.xcloud.tools.gateway.kit.JsonKit;

/**  
 * <p>Title: AccessLogDBKit</p>  
 *
 * <p>Description: 访问日志处理工具类<br>
 * 使用方法：<br>
 * 	1、项目启动时，启动该线程：<br>
 *		AccessLogDBKit.getInstance().start();//启动访问日志存库线程<br>
 * 	2、在需要存储访问日志的地方调用：<br>
 * 		AccessLogDBKit.getInstance().offerQueue(AccessLogEntity entity);<br>
 * 
 * </p>  
 *
 * @author jilong.xiao  
 * @date 2018年5月17日  
 */
public class AccessLogDBKit extends Thread{
	private static final Logger log = LoggerFactory.getLogger(AccessLogDBKit.class);
	//单例
	private static AccessLogDBKit accessLogDBKit = null;
	private AccessLogDBKit(){super("xcloudGatewayAccessLogDBKitThread");}
	//缓冲队列
	private static BlockingQueue<AccessLogEntity> accessLogQueue = new LinkedBlockingQueue<AccessLogEntity>(1024);
	
	public static synchronized AccessLogDBKit getInstance(){
		if(accessLogDBKit == null){
			accessLogDBKit = new AccessLogDBKit();
		}
		return accessLogDBKit;
	}
	
	/**
	 * <p>Title: offerQueue</p>  
	 * <p>Description: 写入访问日志</p>  
	 * @param entity
	 */
	public void offerQueue(AccessLogEntity entity){
		try {
			accessLogQueue.offer(entity);
		} catch (Exception e) {
			log.error("访问日志写入失败",e);
		}
	}
	
	@Override
	public void run() {
		if(log.isDebugEnabled()){
			log.debug("访问日志处理线程启动成功...");
		}
		//缓冲数据
		List<AccessLogEntity> list = new ArrayList<AccessLogEntity>();
		while(true){
			try {
				//take()：取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到BlockingQueue有新的数据被加入;
				list.add(accessLogQueue.take());
				//一次性从BlockingQueue获取所有可用的数据对象（还可以指定获取数据的个数），通过该方法，可以提升获取数据效率；不需要多次分批加锁或释放锁。
				accessLogQueue.drainTo(list);
				
				//遍历list，存入db
				for(AccessLogEntity entity: list){
					log.debug("访问日志存入DB："+JsonKit.toJson(entity));
					//省略...
				}
				
			} catch (Exception e) {
				e.printStackTrace();
				log.error("访问日志存库出现异常：",e);
				try {
					Thread.sleep(1000); //暂停一会，防止异常信息刷屏
				} catch (Exception e1) {
				}
			}finally{
				//清空缓存
				if(list!=null && list.size()>0){
					list.clear();
				}
			}
		}
	}
	
}
